#pragma once
#include <vector>
#include <unordered_map>
#include <algorithm>

#include "constants.h"
#include "classes.h"
#include "tools.h"
#include "optimizer_tools.h"

using namespace std;

class OptLocal
{
public:
    vector<vector<BwType>> edge_site_bw_type_vec;
    vector<BwType> center_site_bw_type_vec;
    int edge_site_low_bw[MAX_N];
    int edge_site_high_bw[MAX_N];
    long long center_site_low_bw;
    long long center_site_high_bw;
    AssignInfo *assign_info;
    int edge_low_index;
    int edge_hight_index;
    int center_low_index;
    int center_hight_index;
    double total_score;
    double edge_site_score;
    double center_site_score;
    unsigned int circle_time_state = 0;
    bool ignore_center_site_cost;
    bool always_keep_center_cost_no_increase;

    OptLocal(AssignInfo &assign_info);
    double opt(double edge_low_quantile, double edge_hight_quantile, double center_low_quantile, double center_hight_quantile, bool ignore_center_site_cost, bool always_keep_center_cost_no_increase);

private:
    void find_local_optimize_assign_t(int t);
    void drop_bandwidth_from_site(int site_id, TAssign *tAssign, vector<int> &safe_bw_uppers);
    bool check_throw_and_select_to_site_id(int &to_site_id, int from_site_id, AlloNode *iter, TAssign *tAssign, vector<int> &safe_bw_uppers);
    bool is_center_cost_decrease(int from_site_id, int to_site_id, int bandwidth, TAssign *tAssign, int stream_id);

    void refresh_state();
    void refresh_edge_site_state(int site_id);
    void refresh_center_site_state();
    vector<int> get_safe_bw_uppers(int t, TAssign *tAssign);
};
